import EventType from "../../model/EventType";
import EventManage from "../event/EventManage";
import PoolObj from "../pool/PoolObj";
import SoundHelp from "../sound/SoundHelp";
import SoundManage from "../sound/SoundManage";
import { AsyncQueue } from "../utils/AsyncQueue";
import PromiseEx from "../utils/PromiseEx";
import Utils from "../utils/Utils";


export default class SpineItem {
    static create(): SpineItem {
        let item = PoolObj.getItemByClass("_spineitem_", SpineItem);
        item._pmsk = new PromiseEx();
        item._pmsk.then(() => item._ready = true)
        return item;
    }

    static recover(obj: SpineItem) {
        PoolObj.recover("_spineitem_", obj);
    }

    //============================================

    private _sk: Laya.Skeleton;
    private _pmsk: PromiseEx;
    private _ready: boolean;
    private _key: number;
    private _step: AsyncQueue = new AsyncQueue();

    /**标识 */
    sign: any;

    setScore(sk: Laya.Skeleton, k: number = -1) {
        this._sk = sk;
        this._key = k;

        return this;
    }

    //设置动画准备完成,设置之后才能进行之后步骤
    setComplete() {
        this._pmsk.resolve();

        return this;
    }

    //设置动画位置
    setP(parent: Laya.Sprite, x?: number, y?: number) {
        this._pmsk.then(() => {
            this._sk.pos(x || 0, y || 0);
            parent.addChild(this._sk);
        })

        return this;
    }

    /**
     * 隐藏并暂停动画
     * @param active 
     * @returns 
     */
    setActive(active: boolean) {
        if (this._ready) {
            this._sk.visible = active;
            active ? this._sk.paused() : this._sk.resume();
            return;
        }
        this._pmsk.then(() => {
            this._sk.visible = active;
            active ? this._sk.paused() : this._sk.resume();

        })
    }


    play(nameOrIndex?: number | string, loop?: boolean, sound?: string, soundDely?: number) {
        let queue = this._step;
        nameOrIndex = nameOrIndex == null ? 0 : nameOrIndex;

        queue.push((next: Function, params: any, args) => {
            this._sk.once(Laya.Event.STOPPED, this, () => next())
            this._sk.play(nameOrIndex, loop);
        })

        if (!Utils.isNil(sound)) {
            soundDely = Utils.isNil(soundDely) ? 0 : soundDely;
            SoundHelp.Instance().playSoundDely(sound, soundDely)
        }

        this.execute();

        return this;

    }

    //清空任务并播放动画
    playNow(nameOrIndex?: number | string, loop?: boolean, sound?: string) {
        if (this._ready) {
            this._step.clear();
            this._sk.stop();
            this.play(nameOrIndex, loop);
            return;
        }
        this._pmsk.then(() => {
            this._step.clear();
            this._sk.stop();
            this.play(nameOrIndex, loop);
        })
    }

    wait(dely: number) {
        let queue = this._step;
        queue.yieldTime(dely);
        this.execute();
        return this;
    }

    call(fun: Laya.Handler) {
        let queue = this._step;
        queue.push((next: Function, params: any, args) => {
            fun.run();
            next();
        })

        this.execute()

        return this;
    }

    /**
     * 跳过当前步骤
     * @param isAni 是否是动画
     */
    stpe(isAni: boolean = true) {

        if (isAni) {
            this._ready && this._sk.stop();
        } else {
            this._step.step();
        }
    }

    dispose() {
        let queue = this._step;
        queue.push((next: Function, params: any, args) => {
            this.destory();
            next();
        })

        this.execute();
    }


    destory() {

        let k = this._key;
        this._key = -1;
        this._ready = false;
        this._step.clear();
        this.sign = null;

        if (this._pmsk) {
            this._pmsk.reject();
            this._pmsk = null;
        }

        if (this._sk) {
            this._sk.destroy();
            this._sk = null;
        }

        if (k > -1) {
            EventManage.I.event(EventType.SK_DESTORY, k)
        }

        SpineItem.recover(this);
    }

    get sk() {
        return this._pmsk.then(() => this._sk)
    }

    private execute() {
        if (this._ready) {
            this._step.play();
        } else {
            this._pmsk.then(() => this._step.play())
        }
    }

}